package com.iamk.tool;

import ij.process.ColorProcessor;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.filechooser.FileNameExtensionFilter;

import net.miginfocom.swing.MigLayout;
import weka.classifiers.Classifier;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.SerializationHelper;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Normalize;
import weka.filters.unsupervised.attribute.ReplaceMissingValues;

import com.iamk.feature.FColor;
import com.iamk.lib.FeaturesColor;
import com.iamk.util.CreateImageRegion;
import com.iamk.util.GetData;
import com.iamk.util.HaarTransform;
import com.iamk.util.ImageUtil;
import com.test.TestGMM;

import de.lmu.ifi.dbs.jfeaturelib.features.Tamura;

public class ImageRetrieval extends JPanel implements ActionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	JButton btnOpenFolder;
	JButton btnSearch;
	
	JLabel lblPath;
	JLabel picImageRetrieval;
	JLabel picImageSegment;
	
	JTextField tfPath;
	JTextArea taLabel;
	
	JScrollPane annotationLabelPanel;
	JScrollPane similarImagePane;
	JPanel mPanelImageRetrieval;
	JPanel mPanelImageResult;
	JPanel mPanelImageSegment;
	JPanel mPanelAnnotationLabel;
	
	JFileChooser dlgChooseFolder;
	
	Image imgRetrieval;
	FColor fImage;
	
	String path;
	
	Instances mTestInstances;
	Instances mTrainInstances;
	
	public ImageRetrieval() {
		super(null);
		setPropertiesComponent();
	}
	
	
	void setPropertiesComponent() {
		// Init view
		lblPath = new JLabel("Path: ");
		lblPath.setSize(new Dimension(50, 20));
		lblPath.setLocation(580, 20);

		btnOpenFolder = new JButton("Open");
		btnOpenFolder.setSize(new Dimension(70, 30));
		btnOpenFolder.setLocation(1060, 20);
		btnOpenFolder.setActionCommand("Open");
		btnOpenFolder.setVisible(true);
		btnOpenFolder.addActionListener(this);
		
		btnSearch = new JButton("Search");
		btnSearch.setSize(new Dimension(90, 30));
		btnSearch.setLocation(1140, 20);
		btnSearch.setActionCommand("Search");
		btnSearch.setVisible(true);
		btnSearch.addActionListener(this);
		
		tfPath = new JTextField();
		tfPath.setSize(420, 30);
		tfPath.setMargin(new Insets(3, 3, 3, 3));
		tfPath.setLocation(620, 20);
		// Panel Image Retrieval
		mPanelImageRetrieval = new JPanel(new MigLayout());
		mPanelImageRetrieval.setBorder(BorderFactory.createTitledBorder("Image Retrieval"));
		mPanelImageRetrieval.setSize(new Dimension(260, 215));
		mPanelImageRetrieval.setLocation(30, 20);
		
		// Panel Image Segment
		mPanelImageSegment = new JPanel(new MigLayout());
		mPanelImageSegment.setBorder(BorderFactory.createTitledBorder("Image Segment"));
		mPanelImageSegment.setSize(new Dimension(260, 215));
		mPanelImageSegment.setLocation(300, 20);
		
		// Panel Annotation Label
		mPanelAnnotationLabel = new JPanel(new BorderLayout());
		mPanelAnnotationLabel.setBorder(BorderFactory.createTitledBorder("Automatic Image Annotation Label"));
		mPanelAnnotationLabel.setSize(new Dimension(600, 170));
		mPanelAnnotationLabel.setLocation(620, 60);
		
		taLabel = new JTextArea();
		annotationLabelPanel = new JScrollPane(taLabel,
				ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
				ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		mPanelAnnotationLabel.add(annotationLabelPanel);
		
		// Panel Result
		mPanelImageResult = new JPanel(new BorderLayout());
		mPanelImageResult.setBorder(BorderFactory.createTitledBorder("Similar Image Result"));
		mPanelImageResult.setSize(new Dimension(1220, 650));
		mPanelImageResult.setLocation(30, 280);

//		txtResult = new JTextArea();
//		similarImagePane = new JScrollPane(txtResult,
//				ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
//				ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//		mPanelImageResult.add(similarImagePane);
		
		this.add(lblPath);
		this.add(tfPath);
		this.add(btnOpenFolder);
		this.add(btnSearch);
		this.add(mPanelImageRetrieval);
		this.add(mPanelImageSegment);
		this.add(mPanelAnnotationLabel);
		this.add(mPanelImageResult);
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		switch (e.getActionCommand()) {
		case "Open":
			dlgChooseFolder = new JFileChooser();
			dlgChooseFolder.setCurrentDirectory(new File("D:\\University\\Ky10\\datasetImage\\MSRC_ObjCategImageDatabase_v2\\ImageTest_21"));
			dlgChooseFolder.setFileSelectionMode(JFileChooser.FILES_ONLY);
			dlgChooseFolder.setAcceptAllFileFilterUsed(true);
			// create filters
			FileNameExtensionFilter dataFileFilter = new FileNameExtensionFilter("Image files (*.jpg)", "jpg");
			dlgChooseFolder.addChoosableFileFilter(dataFileFilter);
			dlgChooseFolder.setFileFilter(dataFileFilter);
			int returnVal = dlgChooseFolder.showOpenDialog(ImageRetrieval.this);
		    if(returnVal == JFileChooser.APPROVE_OPTION) {
				path = dlgChooseFolder.getSelectedFile().toString();
				tfPath.setText(path);
				loadImage(path);
				fImage = new FColor((BufferedImage)imgRetrieval, getFileName(path), "");
				loadImageSegment(fImage.imgSeg);
				CreateImageRegion cir = new CreateImageRegion(path, fImage.mask);
				cir.loadData(path);
				try {
					// Create Data
					mTrainInstances = new Instances(new FileReader("features-tamura-dcd.arff"));
					mTrainInstances.setClassIndex(mTrainInstances.numAttributes() - 1);
					ArrayList<Attribute> mArrAttributes = new ArrayList<Attribute>();
					for (int i = 0; i < mTrainInstances.numAttributes(); i++) {
						mArrAttributes.add(mTrainInstances.attribute(i));
					}
					mTestInstances = new Instances("TestInstances",	mArrAttributes, 0);
					mTestInstances.setClassIndex(mTestInstances.numAttributes() - 1);
					for (int i = 0; i < cir.listRegion.size(); i++) {
						mTestInstances.add(getInstance(cir.listRegion.get(i)));
					}
				
//					BufferedWriter bw = new BufferedWriter(new FileWriter("C:/Users/sev_user/Desktop/data-mcr/data-mcr/Feature Test/features-wavelet2-tamura-dcd-21-test.arff",false));
//					bw.write(mTestInstances.toString());
//					bw.close();
					// Automatic Image Annotation
					AIAWeka(mTrainInstances, mTestInstances);
					
				} catch (IOException e1) {
					e1.printStackTrace();
				}
		    }
			break;
		case "Search":
		default:
			break;
		}
	}
	private void AIAGMM(Instances mTrain, Instances mTest) {
		TestGMM testGMM = new TestGMM();
		double[][] temp;
		int k=1; // Number Gaussian
		// Training
		int c= mTrain.numClasses();
		for (int i = 1; i <= c; i++) {
			temp = GetData.getSubMatrix(GetData.getData(mTrain, c),mTrain.numAttributes() - 1);
			com.jMEF.gmm.Image._loadMixtureModel("GMM_MSCR/label" + c+ ".mix", temp, k, mTrain.numInstances());
		}
		// Testing
		int[] r=testGMM.testGMMofTool(GetData.getSubMatrixWithLabel(GetData.getDataMatrix(mTest),mTest.numAttributes()-1));
		StringBuffer str=new StringBuffer();
		for(int i=0;i<r.length;i++){
			str.append(getStringLabel(r[i])+"/n");
		}
		taLabel.setText(str.toString());
	}
	private void loadImage(String path){
		try {
			imgRetrieval = ImageIO.read(new File(path));
			BufferedImage imgRet = ImageUtil.resizeImage(ImageUtil.imageToBufferedImage(imgRetrieval), 240,180); 
			System.out.println(imgRet.getWidth() + "," + imgRet.getHeight());
			picImageRetrieval = new JLabel(new ImageIcon(imgRet));
			mPanelImageRetrieval.removeAll();
			mPanelImageRetrieval.add(picImageRetrieval);
			mPanelImageRetrieval.revalidate();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void loadImageSegment(Image imgSeg){
		BufferedImage imgRet = ImageUtil.resizeImage(ImageUtil.imageToBufferedImage(imgSeg), 240, 180);
		picImageSegment = new JLabel(new ImageIcon(imgRet));
		mPanelImageSegment.removeAll();
		mPanelImageSegment.add(picImageSegment);
		mPanelImageSegment.revalidate();
	}
	
	private String getFileName(String path){
		String filename = path.substring(path.lastIndexOf("\\")+1,path.length());
		filename = filename.replace(".jpg", "");
		return filename;
	}
	
	private DenseInstance getInstance(Image imgRegion){
		ArrayList<Double> listFeatures = new ArrayList<Double>();
		Tamura mDescriptor = new Tamura();
        mDescriptor.run(new ColorProcessor(imgRegion));
        List<double[]> features = mDescriptor.getFeatures();
		for (double[] feature : features) {
			for(int l = 0; l < feature.length; l++){
				listFeatures.add(feature[l]);
			}
		}
		
		FeaturesColor mColorDescriptor = new FeaturesColor(imgRegion);
        List<Double> myfeatures = mColorDescriptor.getFeatures();
        for(int i = 0; i < myfeatures.size(); i++){
        	listFeatures.add(myfeatures.get(i));
        }

        double[] arrFeature = convertList2Array(listFeatures);
        DenseInstance newInstance = new DenseInstance(1.0, arrFeature);
        newInstance.setMissing(newInstance.numAttributes()-1);
        return newInstance;
	}
	
	private DenseInstance getInstanceWavelet(Image imgRegion){
		ArrayList<Double> listFeatures = new ArrayList<Double>();
		HaarTransform mHaar = new HaarTransform();
		BufferedImage imgWavelet = mHaar.foward(ImageUtil.imageToBufferedImage(imgRegion), 2);
		BufferedImage imgApp2 = imgWavelet.getSubimage(0, 0, imgWavelet.getWidth()/4, imgWavelet.getHeight()/4);
		BufferedImage imgD2 = imgWavelet.getSubimage(imgWavelet.getWidth()/4, imgWavelet.getHeight()/4, imgWavelet.getWidth()/4, imgWavelet.getHeight()/4);
		BufferedImage imgD1 = imgWavelet.getSubimage(imgWavelet.getWidth()/2, imgWavelet.getHeight()/2, imgWavelet.getWidth()/2, imgWavelet.getHeight()/2);
		
		Tamura mDescriptorApp2 = new Tamura();
        mDescriptorApp2.run(new ColorProcessor(imgApp2));
        List<double[]> featuresApp2 = mDescriptorApp2.getFeatures();
		for (double[] feature : featuresApp2) {
			for(int l = 0; l < feature.length; l++){
				listFeatures.add(feature[l]);
			}
		}
		
		Tamura mDescriptorD2 = new Tamura();
        mDescriptorD2.run(new ColorProcessor(imgD2));
        List<double[]> featuresD2 = mDescriptorD2.getFeatures();
		for (double[] feature : featuresD2) {
			for(int l = 0; l < feature.length; l++){
				listFeatures.add(feature[l]);
			}
		}
		
		Tamura mDescriptorD1 = new Tamura();
        mDescriptorD1.run(new ColorProcessor(imgD1));
        List<double[]> featuresD1 = mDescriptorD1.getFeatures();
		for (double[] feature : featuresD1) {
			for(int l = 0; l < feature.length; l++){
				listFeatures.add(feature[l]);
			}
		}
		
		FeaturesColor mColorDescriptorApp2 = new FeaturesColor(imgApp2);
        List<Double> myfeaturesApp2 = mColorDescriptorApp2.getFeatures();
        for(int i = 0; i < myfeaturesApp2.size(); i++){
        	listFeatures.add(myfeaturesApp2.get(i));
        }

        FeaturesColor mColorDescriptorD2 = new FeaturesColor(imgD2);
        List<Double> myfeaturesD2 = mColorDescriptorD2.getFeatures();
        for(int i = 0; i < myfeaturesD2.size(); i++){
        	listFeatures.add(myfeaturesD2.get(i));
        }
        
		FeaturesColor mColorDescriptorD1 = new FeaturesColor(imgD1);
        List<Double> myfeaturesD1 = mColorDescriptorD1.getFeatures();
        for(int i = 0; i < myfeaturesD1.size(); i++){
        	listFeatures.add(myfeaturesD1.get(i));
        }
        double[] arrFeature = convertList2Array(listFeatures);
        DenseInstance newInstance = new DenseInstance(1.0, arrFeature);
        newInstance.setMissing(newInstance.numAttributes()-1);
        return newInstance;
	}
	
	private double[] convertList2Array(ArrayList<Double> list){
		double[] arr = new double[list.size()+1];
		for(int i = 0; i < list.size(); i++){
        	arr[i] = list.get(i);
        }
		return arr;
	}
	
	private void AIAWeka(Instances mTrain,Instances mTest){
		try {
			// Clean up training data
			ReplaceMissingValues replace = new ReplaceMissingValues();
			replace.setInputFormat(mTrain);
			Instances training_data_filter1 = Filter.useFilter(mTrain, replace);

			// Normalize training data
			Normalize norm = new Normalize();
			norm.setInputFormat(training_data_filter1);
			Instances processed_training_data = Filter.useFilter(training_data_filter1, norm);

			// Set class attribute for pre-processed training data
			processed_training_data.setClassIndex(processed_training_data.numAttributes() - 1);


			// build classifier
			Classifier cls = (Classifier)SerializationHelper.read(System.getProperty("user.dir") + "/model/SVM-tamura-dcd-21.model"); // Load Classifier from saved model

			// Clean up test data
			replace.setInputFormat(mTest);
			Instances test_data_filter1 = Filter.useFilter(mTest, replace);

			// Normalize test data
			norm.setInputFormat(training_data_filter1);
			Instances processed_test_data = Filter.useFilter(test_data_filter1,	norm);

			// Set class attribute for pre-processed training data
			processed_test_data.setClassIndex(processed_test_data.numAttributes() - 1);

			// int num_correct=0;
			StringBuilder sbLabel = new StringBuilder();
			for (int i = 0; i < processed_test_data.numInstances(); i++) {
				Instance currentInst = processed_test_data.instance(i);
				int predictedClass = (int)cls.classifyInstance(currentInst);
				sbLabel.append(getStringLabel(predictedClass+1) + "\n");
			}
			taLabel.setText(sbLabel.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private String getStringLabel(int label){
		String slabel = "";
		switch (label) {
		case 1:
			slabel = "building";
			break;
		case 2:
			slabel = "Grass";
			break;
		case 3:
			slabel = "Tree";
			break;
		case 4:
			slabel = "Cow";
			break;
		case 5:
			slabel = "Sheep";
			break;
		case 6:
			slabel = "Sky";
			break;
		case 7:
			slabel = "Aeroplane";
			break;
		case 8:
			slabel = "Water";
			break;
		case 9:
			slabel = "Face";
			break;
		case 10:
			slabel = "Car";
			break;
		case 11:
			slabel = "Bicycle";
			break;
		case 12:
			slabel = "Flower";
			break;
		case 13:
			slabel = "Sign";
			break;
		case 14:
			slabel = "Bird";
			break;
		case 15:
			slabel = "Book";
			break;
		case 16:
			slabel = "Chair";
			break;
		case 17:
			slabel = "Road";
			break;
		case 18:
			slabel = "Cat";
			break;
		case 19:
			slabel = "Dog";
			break;
		case 20:
			slabel = "Body";
			break;
		case 21:
			slabel = "Boat";
			break;
		default:
			slabel = "None";
			break;
		}
		return slabel;
	}
}